package com.lframework.jh.push.plugin.ali.sms;

import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.QuerySendDetailsRequest;
import com.aliyun.dysmsapi20170525.models.QuerySendDetailsResponse;
import com.aliyun.dysmsapi20170525.models.QuerySendDetailsResponseBody;
import com.aliyun.dysmsapi20170525.models.QuerySendDetailsResponseBody.QuerySendDetailsResponseBodySmsSendDetailDTOsSmsSendDetailDTO;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import com.lframework.jh.push.core.exceptions.impl.DefaultClientException;
import com.lframework.jh.push.core.exceptions.impl.DefaultSysException;
import com.lframework.jh.push.core.exceptions.impl.InputErrorException;
import com.lframework.jh.push.core.utils.CollectionUtil;
import com.lframework.jh.push.core.utils.DateUtil;
import com.lframework.jh.push.core.utils.JsonUtil;
import com.lframework.jh.push.core.utils.StringUtil;
import com.lframework.jh.push.plugin.core.SmsPushChannel;
import com.lframework.jh.push.plugin.core.SmsPushChannelParams;
import com.lframework.jh.push.plugin.core.SmsPushResp;
import com.lframework.jh.push.plugin.core.constants.PushConstants;
import com.lframework.jh.push.plugin.core.dto.QuerySmsPushResultDetailDto;
import com.lframework.jh.push.plugin.core.dto.QuerySmsPushResultDetailRespDto;
import com.lframework.jh.push.plugin.core.dto.QuerySmsPushResultPageDto;
import com.lframework.jh.push.plugin.core.dto.QuerySmsPushResultPageRespDto;
import com.lframework.jh.push.plugin.core.enums.SmsQueryType;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 文档地址 https://next.api.aliyun.com/api/Dysmsapi/2017-05-25/SendSms
 */
@Slf4j
@Component("ali_sms" + PushConstants.SMS_PUSH_CHANNEL_BEAN_NAME_SUFFIX)
public class AliSmsPushChannel implements SmsPushChannel {

    @Override
    public Class<? extends SmsPushChannelParams> getClazz() {
        return AliSmsPushChannelParams.class;
    }

    @Override
    public SmsPushResp push(SmsPushChannelParams params) throws Exception {

        AliSmsPushChannelParams channelParams = (AliSmsPushChannelParams) params;
        AliSmsExtra extra = JsonUtil.parseObject(channelParams.getExtra(), AliSmsExtra.class);
        Client client = this.createClient(params);

        SendSmsRequest sendReq = new SendSmsRequest()
            .setPhoneNumbers(channelParams.getPhoneNumbers())
            .setSignName(extra.getSignName())
            .setTemplateCode(extra.getTemplateCode())
            .setTemplateParam(extra.getTemplateParam());
        SendSmsResponse sendResp = client.sendSms(sendReq);
        String code = sendResp.getBody().getCode();
        if (sendResp.getBody() == null || !"OK".equals(code)) {
            log.error("阿里云短信发送失败，错误信息: {}", sendResp.body.message);
            throw new DefaultClientException(sendResp.body.message);
        }

        AliSmsPushResp resp = new AliSmsPushResp();
        resp.setRequestId(sendResp.getBody().getRequestId());
        String[] phoneNumbers = channelParams.getPhoneNumbers().split(",");

        List<AliSmsPushDetailResp> detailResps = new ArrayList<>();
        for (String phoneNumber : phoneNumbers) {
            AliSmsPushDetailResp detailResp = new AliSmsPushDetailResp();
            detailResp.setBizId(sendResp.getBody().getBizId());
            detailResp.setPhoneNumber(phoneNumber);
            detailResps.add(detailResp);
        }
        resp.setDetails(detailResps);
        return resp;
    }

    @Override
    public QuerySmsPushResultDetailRespDto query(QuerySmsPushResultDetailDto dto) throws Exception {

        QuerySendDetailsRequest req = new QuerySendDetailsRequest()
            .setPhoneNumber(dto.getPhoneNumber())
            .setBizId(dto.getBizId())
            .setSendDate(DateUtil.formatDate(dto.getPushTime().toLocalDate(), "yyyyMMdd"))
            .setCurrentPage(1L)
            .setPageSize(50L);
        QuerySendDetailsResponse queryResp = this.createClient(dto.getParams())
            .querySendDetails(req);

        QuerySendDetailsResponseBody body = queryResp.getBody();
        if (body != null) {
            QuerySendDetailsResponseBody.QuerySendDetailsResponseBodySmsSendDetailDTOs smsSendDetailDTOs = body.getSmsSendDetailDTOs();
            if (smsSendDetailDTOs != null) {
                List<QuerySendDetailsResponseBody.QuerySendDetailsResponseBodySmsSendDetailDTOsSmsSendDetailDTO> list = smsSendDetailDTOs.getSmsSendDetailDTO();
                if (CollectionUtil.isNotEmpty(list)) {
                    QuerySendDetailsResponseBodySmsSendDetailDTOsSmsSendDetailDTO detailDTO = list.get(
                        0);
                    QuerySmsPushResultDetailRespDto detailRespDto = new QuerySmsPushResultDetailRespDto();
                    detailRespDto.setPhoneNumber(detailDTO.getPhoneNum());
                    if (detailDTO.getSendStatus() == 3) {
                        detailRespDto.setStatus(3);
                        detailRespDto.setSuccessTime(
                            DateUtil.parse(detailDTO.getReceiveDate(), "yyyy-MM-dd HH:mm:ss"));
                        detailRespDto.setContent(detailDTO.getContent());
                    } else if (detailDTO.getSendStatus() == 2) {
                        detailRespDto.setStatus(2);
                        detailRespDto.setErrorMsg(detailDTO.getErrCode());
                    } else {
                        detailRespDto.setStatus(1);
                    }

                    return detailRespDto;
                }
            }
        }

        return null;
    }

    @Override
    public QuerySmsPushResultPageRespDto query(QuerySmsPushResultPageDto dto) throws Exception {
        throw new DefaultSysException("不支持分页方式查询");
    }

    private Client createClient(SmsPushChannelParams params) throws Exception {
        AliSmsPushChannelParams channelParams = (AliSmsPushChannelParams) params;
        Config config = new Config();
        config.setAccessKeyId(channelParams.getAccessKeyId());
        config.setAccessKeySecret(channelParams.getAccessKeySecret());

        return new Client(config);
    }

    @Override
    public void validExtra(String extra) {
        if (StringUtil.isBlank(extra)) {
            throw new InputErrorException("extra不能为空！");
        }
        if (!JsonUtil.isJsonObject(extra)) {
            throw new InputErrorException("extra格式有误，应为JSON字符串！");
        }
        AliSmsExtra smsExtra = JsonUtil.parseObject(extra, AliSmsExtra.class);
        if (StringUtil.isBlank(smsExtra.getSignName())) {
            throw new InputErrorException("extra.signName不能为空！");
        }

        if (StringUtil.isBlank(smsExtra.getTemplateCode())) {
            throw new InputErrorException("extra.templateCode不能为空！");
        }

        if (StringUtil.isNotBlank(smsExtra.getTemplateParam())) {
            if (!JsonUtil.isJsonObject(smsExtra.getTemplateParam())) {
                throw new InputErrorException("extra.templateParam格式有误，应为JSON字符串！");
            }
        }
    }

    @Override
    public Integer allowSmsCount() {
        return 1000;
    }

    @Override
    public SmsQueryType getQueryType() {
        return SmsQueryType.DETAIL;
    }
}
